home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / adg_7_8.zip / SETUP.C < prev    next >
Text File  |  1991-02-21  |  14KB  |  409 lines

  1. /****************************************************************************
  2. Module name: Setup.C
  3. Programmer : Jeffrey M. Richter.
  4. *****************************************************************************/
  5.  
  6. #include "..\nowindws.h"
  7. #undef NOATOM
  8. #undef NOCTLMGR
  9. #undef NOKERNEL
  10. #undef NOLFILEIO
  11. #undef NOLSTRING
  12. #undef NOMB
  13. #undef NOMEMMGR
  14. #undef NOMINMAX
  15. #undef NOMSG
  16. #undef NOOPENFILE
  17. #undef NORESOURCE
  18. #undef NOSHOWWINDOW
  19. #undef NOSYSMETRICS
  20. #undef NOUSER
  21. #undef NOWINMESSAGES
  22. #undef NOWINOFFSETS
  23. #undef NOWINSTYLES
  24. #include <windows.h>
  25. #include <dde.h>
  26.  
  27. #include <dos.h>
  28. #include <direct.h>
  29. #include <string.h>
  30.  
  31. #include "Setup.H"
  32. #include "SetupInf.H"
  33. #include "..\Meter.04\Meter.H"
  34.  
  35. BOOL NEAR PASCAL CreateDstDirTree (HWND hDlgStatus);
  36. BOOL NEAR PASCAL CopyAllFiles (HWND hDlgStatus);
  37. BOOL NEAR PASCAL CreatePMInfo (HANDLE hInstance);
  38. #define WasCancelled(hDlg) (!IsWindowEnabled(GetDlgItem(hDlg, IDCANCEL)))
  39.  
  40. char _szAppName[] = "Setup";
  41. HANDLE _hInstance;
  42. char _szSrcDir[MAXDIR] = "x:\\"; // Where SETUP.EXE was run from.
  43. char _szDstDir[MAXDIR];
  44.  
  45. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  46.                     LPSTR lpszCmdLine, int nCmdShow) {
  47.    int nResult;
  48.    HWND hDlgStatus;
  49.    FARPROC fpStatDlgProc, fpProc;
  50.    HANDLE hLibMeter;
  51.    DWORD dwDiskSpaceNeeded, dwFreeDiskSpace;
  52.    struct diskfree_t DiskFreeSpace;
  53.    char szBuf[100];
  54.  
  55.    // Don't let another instance of this application execute.
  56.    if (hPrevInstance != NULL) return(0);
  57.  
  58.    // Prepare the DDE Client window class so that we can use it later.
  59.    if (!RegisterDDEClient(hInstance)) return(0);
  60.  
  61.    // Initialize the default source path so that it uses the same drive 
  62.    // letter that the SETUP.EXE application was executed from.
  63.    GetModuleFileName(hInstance, _szSrcDir, sizeof(_szSrcDir));
  64.     *(_fstrrchr(_szSrcDir, '\\') + 1) = 0;
  65.  
  66.    _hInstance = hInstance;
  67.  
  68.    // Check that the METER.DLL is available at the beginning.
  69.    wsprintf(szBuf, "%sMETER.DLL", (LPSTR) _szSrcDir);
  70.    hLibMeter = LoadLibrary(szBuf);
  71.    if (hLibMeter < 32) {
  72.       MsgBox(hInstance, NULL, IDS_NOMETERLIB, _szAppName,
  73.          MB_ICONINFORMATION | MB_OK | MB_TASKMODAL);
  74.       return(0);
  75.    }
  76.  
  77.    // Read the SETUP.INF file into memory.
  78.    wsprintf(szBuf, "%s%sSETUP.INF", (LPSTR) _szSrcDir, (LPSTR)
  79.       ((*(_fstrrchr(_szSrcDir, '\\') + 1) == 0) ? "" : "\\"));
  80.  
  81.    nResult = (SIM_INITIALIZE_ERROR) SetupInfoSys(SIM_INITIALIZE, 0, szBuf);
  82.    if (nResult != SIM_INIT_NOERROR) {
  83.       MsgBox(hInstance, NULL,
  84.          (nResult == SIM_INIT_NOMEM) ? IDS_NOMEMORY : IDS_NOSETUPINFOFILE,
  85.          _szAppName, MB_ICONINFORMATION | MB_OK | MB_TASKMODAL,
  86.             (LPSTR) szBuf);
  87.       FreeLibrary(hLibMeter);
  88.       return(0);
  89.    }
  90.  
  91.    // Get the amount of memory (in K) that is needed for the installation.
  92.    dwDiskSpaceNeeded = SetupInfoSys(SIM_GETSPACENEEDED, 0, 0);
  93.  
  94.    // Create the Status dialog box.
  95.    fpStatDlgProc = MakeProcInstance(StatusDlgProc, hInstance);
  96.    hDlgStatus = CreateDialog(hInstance, MAKEINTRESOURCE(DLG_STATUS),
  97.       NULL, fpStatDlgProc);
  98.  
  99.    do {
  100.       // Welcome user to setup program and prompt for destination directory.
  101.       fpProc = MakeProcInstance(WelcomeDlgProc, hInstance);
  102.       nResult = DialogBox(hInstance, MAKEINTRESOURCE(DLG_WELCOME),
  103.          NULL, fpProc);
  104.       FreeProcInstance(fpProc);
  105.       if (nResult == IDCANCEL) break;
  106.  
  107.       // check if there is sufficient disk space on the destination drive.
  108.       _dos_getdiskfree(_szDstDir[0] - 'A' + 1, &DiskFreeSpace);
  109.       dwFreeDiskSpace = ((DWORD) DiskFreeSpace.avail_clusters *
  110.                          (DWORD) DiskFreeSpace.sectors_per_cluster *
  111.                          (DWORD) DiskFreeSpace.bytes_per_sector) / 1024UL;
  112.  
  113.       if (dwFreeDiskSpace < dwDiskSpaceNeeded) {
  114.          MsgBox(hInstance, NULL, IDS_NODISKSPACE, _szAppName,
  115.             MB_OK | MB_ICONINFORMATION | MB_TASKMODAL,
  116.             _szDstDir[0], dwFreeDiskSpace, dwDiskSpaceNeeded);
  117.          continue;
  118.       }
  119.  
  120.       // Try to create the destination directory tree.
  121.       ShowWindow(hDlgStatus, SW_SHOW);
  122.       UpdateWindow(hDlgStatus);
  123.       nResult = CreateDstDirTree(hDlgStatus);
  124.       ShowWindow(hDlgStatus, SW_HIDE);
  125.  
  126.       if (nResult == FALSE) {
  127.          // If the directory tree cannot be created, force loop to repeat.
  128.          dwFreeDiskSpace = 0;
  129.       }
  130.  
  131.    } while (dwFreeDiskSpace < dwDiskSpaceNeeded);
  132.  
  133.    if (nResult == IDCANCEL) {
  134.       DestroyWindow(hDlgStatus);
  135.       FreeProcInstance(fpStatDlgProc);
  136.       FreeLibrary(hLibMeter);
  137.       return(0);
  138.    }
  139.  
  140.    // Make the destination directory the current directory.
  141.    chdir(_szDstDir);
  142.  
  143.    // Try to copy the files.
  144.    ShowWindow(hDlgStatus, SW_SHOW);
  145.    UpdateWindow(hDlgStatus);
  146.    nResult = CopyAllFiles(hDlgStatus);
  147.    ShowWindow(hDlgStatus, SW_HIDE);
  148.  
  149.    // Cleanup the things that we no longer need.
  150.    DestroyWindow(hDlgStatus);
  151.    FreeProcInstance(fpStatDlgProc);
  152.    FreeLibrary(hLibMeter);
  153.  
  154.    if (nResult == FALSE) {
  155.       // Installation not complete.
  156.       MsgBox(hInstance, NULL, IDS_SETUPNOGOOD, _szAppName,
  157.          MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
  158.       return(0);
  159.    }
  160.  
  161.    MsgBox(hInstance, NULL,
  162.       CreatePMInfo(hInstance) ? IDS_PMADDOK : IDS_PMADDNOGOOD,
  163.       _szAppName, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
  164.     return(0);
  165. }
  166.  
  167.  
  168. // ********** Functions for Creating the destination directory tree **********
  169. BOOL NEAR PASCAL CreateDstDirTree (HWND hDlgStatus) {
  170.    int nResult, nMaxDirs, nDirNum;
  171.    char szBuf[MAXDIR]; MSG Msg;
  172.  
  173.    SetDlgItemText(hDlgStatus, ID_STATLINE1, "Creating destination directory tree...");
  174.    nMaxDirs = (int) SetupInfoSys(SIM_GETNUMDIRS, 0, 0);
  175.    SendDlgItemMessage(hDlgStatus, ID_METER, MM_SETPARTSCOMPLETE, 0, 0);
  176.    SendDlgItemMessage(hDlgStatus, ID_METER, MM_SETPARTSINJOB, nMaxDirs + 1, 0);
  177.    SetDlgItemText(hDlgStatus, ID_STATLINE2, _szDstDir);
  178.  
  179.    // Create the destination directory.
  180.    nResult = chdir(_szDstDir);
  181.    if (nResult != 0) {
  182.       nResult = mkdir(_szDstDir);
  183.       if (nResult != 0) {
  184.          MsgBox(_hInstance, hDlgStatus, IDS_CANTMAKEDIR, _szAppName,
  185.             MB_ICONINFORMATION | MB_OK, (LPSTR) _szDstDir);
  186.          return(FALSE);
  187.       } else chdir(_szDstDir);
  188.    }
  189.    SendDlgItemMessage(hDlgStatus, ID_METER, MM_SETPARTSCOMPLETE, 1, 0);
  190.  
  191.    // Create any subdirectories under the destination directory.
  192.    for (nDirNum = 0; nDirNum < nMaxDirs; nDirNum++) {
  193.       // Let some other applications execute.
  194.       while (PeekMessage(&Msg, NULL, NULL, NULL, PM_REMOVE)) {
  195.          TranslateMessage(&Msg);
  196.          DispatchMessage(&Msg);
  197.       }
  198.  
  199.       if (WasCancelled(hDlgStatus)) {
  200.          nResult = IDCANCEL;
  201.          break;
  202.       }
  203.  
  204.       wsprintf(szBuf, "%s%s", (LPSTR) _szDstDir,
  205.          (LPSTR) ((*(_fstrrchr(_szDstDir, '\\') + 1) == 0) ? "" : "\\"));
  206.       SetupInfoSys(SIM_GETDIR, nDirNum, _fstrchr(szBuf, 0));
  207.       SetDlgItemText(hDlgStatus, ID_STATLINE2, szBuf);
  208.  
  209.       nResult = chdir(szBuf);
  210.       if (nResult != 0) {
  211.          nResult = mkdir(szBuf);
  212.          if (nResult != 0) {
  213.             MsgBox(_hInstance, hDlgStatus, IDS_CANTMAKEDIR, _szAppName,
  214.                MB_ICONINFORMATION | MB_OK, (LPSTR) szBuf);
  215.             nResult = IDCANCEL;
  216.             break;
  217.          } else chdir(szBuf);
  218.       }
  219.       nResult = IDOK;
  220.       SendDlgItemMessage(hDlgStatus, ID_METER, MM_SETPARTSCOMPLETE, nDirNum + 2, 0);
  221.    }
  222.    return(nResult != IDCANCEL);
  223. }
  224.  
  225.  
  226. // ******************* Functions for Copying Files ***************************
  227.  
  228. typedef enum {
  229.    CFE_NOERROR,
  230.    CFE_NOMEMORY,
  231.    CFE_CANTOPENSRC,
  232.    CFE_CANTOPENDST,
  233. } COPYFILE_ERROR;
  234.  
  235.  
  236. COPYFILE_ERROR NEAR PASCAL CopyFile (LPSTR szSrcPath, LPSTR szDstPath) {
  237.    const WORD wBufferSize = 65535u;
  238.    int nSrcFile, nDstFile;
  239.    WORD wBytesRead, wDate, wTime;
  240.    OFSTRUCT ofSrc, ofDst;
  241.    LPSTR lpBuffer;
  242.    GLOBALHANDLE hMem;
  243.  
  244.    nSrcFile = OpenFile(szSrcPath, &ofSrc, OF_READ);
  245.    if (nSrcFile == -1) return(CFE_CANTOPENSRC);
  246.  
  247.    hMem = GlobalAlloc(GMEM_MOVEABLE, wBufferSize);
  248.    if (hMem == NULL) {
  249.       _lclose(nSrcFile);
  250.       return(CFE_NOMEMORY);
  251.    }
  252.  
  253.    nDstFile = OpenFile(szDstPath, &ofDst, OF_CREATE | OF_WRITE);
  254.    if (nDstFile == -1) {
  255.       _lclose(nSrcFile);
  256.       GlobalFree(hMem);
  257.       return(CFE_CANTOPENDST);
  258.    }
  259.  
  260.    lpBuffer = GlobalLock(hMem);
  261.    do {
  262.       wBytesRead = _lread(nSrcFile, lpBuffer, wBufferSize);
  263.       _lwrite(nDstFile, lpBuffer, wBytesRead);
  264.    } while (wBytesRead == wBufferSize);
  265.    GlobalUnlock(hMem);
  266.  
  267.    // Make the destination file have the same time stamp as the source file.
  268.    _dos_getftime(nSrcFile, &wDate, &wTime);
  269.    _dos_setftime(nDstFile, wDate, wTime);
  270.    _lclose(nDstFile);
  271.  
  272.    GlobalFree(hMem);
  273.    _lclose(nSrcFile);
  274.    return(CFE_NOERROR);
  275. }
  276.  
  277.  
  278.  
  279.  
  280. BOOL NEAR PASCAL CopyAllFiles (HWND hDlgStatus) {
  281.    int nMaxFiles, nFileNum, nResult; COPYFILE_ERROR CFE;
  282.    char szSrcPath[MAXPATH], szDstPath[MAXPATH], szFileName[MAXFILENAME];
  283.    char szFileDesc[MAXFILEDESC], szDir[MAXDIRDESC], szDiskDesc[MAXDISKDESC];
  284.    MSG Msg; FARPROC fpProc;
  285.  
  286.    HANDLE hDlgRes;
  287.  
  288.    // Get the handle of the "InsertDisk" dialog box from the EXEcutable file.
  289.    hDlgRes = FindResource(_hInstance, MAKEINTRESOURCE(DLG_INSERTDISK), RT_DIALOG);
  290.  
  291.    // Get the memory handle of the "InsertDisk" dialog box in memory.
  292.    // The block is already in memory because the dialog box is marked as
  293.    // PRELOAD FIXED.
  294.    hDlgRes = LoadResource(_hInstance, hDlgRes);
  295.  
  296.    // Force the memory block to be locked down.  This prohibits Windows 
  297.    // from discarding the dialog box template from memory.
  298.    LockResource(hDlgRes);
  299.  
  300.    SetDlgItemText(hDlgStatus, ID_STATLINE1, "Copying files...");
  301.    nMaxFiles = (int) SetupInfoSys(SIM_GETNUMFILES, 0, 0);
  302.    SendDlgItemMessage(hDlgStatus, ID_METER, MM_SETPARTSCOMPLETE, 0, 0);
  303.    SendDlgItemMessage(hDlgStatus, ID_METER, MM_SETPARTSINJOB, nMaxFiles, 0);
  304.  
  305.    fpProc = MakeProcInstance(InsertDiskDlgProc, _hInstance);
  306.    for (nFileNum = 0; nFileNum < nMaxFiles; nFileNum++) {
  307.       SetupInfoSys(SIM_GETFILEDESC, nFileNum, szFileDesc);
  308.       SetupInfoSys(SIM_GETFILENAME, nFileNum, szFileName);
  309.       SetupInfoSys(SIM_GETFILEDIR,  nFileNum, szDir);
  310.       SetupInfoSys(SIM_GETFILEDISK, nFileNum, szDiskDesc);
  311.       SetDlgItemText(hDlgStatus, ID_STATLINE2, szFileDesc);
  312.  
  313.       wsprintf(szDstPath, "%s%s%s\\%s", (LPSTR) _szDstDir, (LPSTR) 
  314.          ((*(_fstrrchr(_szDstDir, '\\') + 1) == 0) ? "" : "\\"),
  315.          (LPSTR) szDir, (LPSTR) szFileName);
  316.  
  317.       do {
  318.          // Let other applications execute.
  319.          while (PeekMessage(&Msg, NULL, NULL, NULL, PM_REMOVE)) {
  320.             TranslateMessage(&Msg);
  321.             DispatchMessage(&Msg);
  322.          }
  323.  
  324.          if (WasCancelled(hDlgStatus)) {
  325.             nResult = IDCANCEL;
  326.             break;
  327.          }
  328.  
  329.          wsprintf(szSrcPath, "%s%s%s\\%s", (LPSTR) _szSrcDir, (LPSTR) 
  330.             ((*(_fstrrchr(_szSrcDir, '\\') + 1) == 0) ? "" : "\\"),
  331.             (LPSTR) szDir, (LPSTR) szFileName);
  332.  
  333.          nResult = IDOK;
  334.          if (!SetupInfoSys(SIM_ISFILECOMPRESSED, nFileNum, 0)) {
  335.             CFE = CopyFile(szSrcPath, szDstPath);
  336.  
  337.             switch (CFE) {
  338.  
  339.                case CFE_NOERROR:
  340.                   nResult = IDOK;
  341.                   break;
  342.  
  343.                case CFE_NOMEMORY:
  344.                   nResult = MsgBox(_hInstance, hDlgStatus, IDS_NOMEMORYCOPY,
  345.                      _szAppName, MB_ICONINFORMATION | MB_RETRYCANCEL);
  346.                   break;
  347.  
  348.                case CFE_CANTOPENSRC:
  349.                   nResult = DialogBoxParam(_hInstance,
  350.                      MAKEINTRESOURCE(DLG_INSERTDISK), hDlgStatus, fpProc,
  351.                      (LONG) (LPSTR) szDiskDesc);
  352.  
  353.                   // Normally, Windows would have discarded the dialog box 
  354.                   // template from memory after the dialog box had been 
  355.                   // created.  By forcing the memory block to be locked by the
  356.                   // call to LockResource() above, the template will NOT be 
  357.                   // discarded.  If the template were discarded, the next time
  358.                   // this dialog box needed to be created Windows would have 
  359.                   // to load the template from the EXEcutable file.  However,
  360.                   // the SETUP.EXE file is probably not on the diskette that 
  361.                   // is currently in the drive.  This would cause the program 
  362.                   // to behave erratically.
  363.                   break;
  364.  
  365.                case CFE_CANTOPENDST:
  366.                   nResult = MsgBox(_hInstance, hDlgStatus, IDS_CANTOPENDST,
  367.                      _szAppName, MB_ICONINFORMATION | MB_RETRYCANCEL);
  368.                   break;
  369.             }
  370.          } else {
  371.             // Use decompression function to copy the file.
  372.          }
  373.  
  374.          // Make sure that the user really wants to cancel Setup.
  375.          if (nResult == IDCANCEL) {
  376.             nResult = MsgBox(_hInstance, hDlgStatus, IDS_QUERYABORT,
  377.                _szAppName, MB_ICONQUESTION | MB_YESNO);
  378.             if (nResult == IDYES) {
  379.                nResult = IDCANCEL;
  380.                break;
  381.             }
  382.          }
  383.  
  384.       } while (nResult != IDCANCEL && CFE != CFE_NOERROR);
  385.       if (nResult == IDCANCEL) break;
  386.  
  387.       SendDlgItemMessage(hDlgStatus, ID_METER, MM_SETPARTSCOMPLETE,
  388.          nFileNum + 1, 0);
  389.    }
  390.  
  391.    // The dialog box template is no longer necessary to keep around so
  392.    // it may be unlocked and removed from memory.
  393.    UnlockResource(hDlgRes);
  394.    FreeResource(hDlgRes);
  395.  
  396.    FreeProcInstance(fpProc);
  397.    return(nResult != IDCANCEL);
  398. }
  399.  
  400. // *********************** Miscellaneous Function ****************************
  401. int FAR cdecl MsgBox (HANDLE hInstance, HWND hWnd, WORD wID,
  402.                    LPSTR szCaption, WORD wType, ...) {
  403.    char szResString[200], szText[200];
  404.    void FAR *VarArgList = (WORD FAR *) &wType + 1;
  405.    LoadString(hInstance, wID, szResString, sizeof(szResString) - 1);
  406.    wvsprintf(szText, szResString, VarArgList);
  407.    return(MessageBox(hWnd, szText, szCaption, wType));
  408. }
  409.